package com.nemodynamic.cattivial.gamecenter;

import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import com.nemodynamic.cattivial.gamecenter.beans.Challenge;
import com.nemodynamic.cattivial.gamecenter.beans.ChallengeGamer;
import com.nemodynamic.cattivial.gamecenter.beans.ChallengeStatus;
import com.nemodynamic.cattivial.gamecenter.beans.ChallengerStatus;
import com.nemodynamic.cattivial.utils.DLog;
import com.parse.ParseException;
import com.parse.ParseInstallation;
import com.parse.ParseObject;
import com.parse.ParsePush;
import com.parse.ParseQuery;
import com.parse.SaveCallback;
import com.parse.SendCallback;

public class ChallengeUtils {
	public static String gamerId;
	public static String gamerName;
	private static final String TAG = "ChallengeUtils";

	private static final String CHALLENGE_GAMER_OBJ = "ChallengeGamer";
	private static final String CHALLENGE_GAMER_ID = "challenge_gamerID";
	private static final String CHALLENGE_GAMER_NAME = "challenge_gamer_name";

	private static final String NOTIFICATION_MESSAGE = "notification_message";
	// actions
	public static final String ACTION_PROPOSE_CHALLENGE = "gamecenter.intent.action.PROPOSE_CHALLENGE";
	public static final String ACTION_ACCEPT_CHALLENGE = "gamecenter.intent.action.ACCEPT_CHALLENGE";
	public static final String ACTION_START_CHALLENGE = "gamecenter.intent.action.START_CHALLENGE";
	public static final String ACTION_FINISHED_CHALLENGE = "gamecenter.intent.action.FINISH_CHALLENGE";

	/**
	 * Every time that is called installation time is refreshed
	 * 
	 * @param gamerId
	 * @param gamerName
	 */
	public static void initGameForChallenges(String gamerId, String gamerName) {
		ChallengeUtils.gamerId = gamerId;
		ChallengeUtils.gamerName = gamerName;
		ParseInstallation installation = ParseInstallation.getCurrentInstallation();
		installation.put(CHALLENGE_GAMER_ID, gamerId);
		ParseObject challengeGamerEntry = new ParseObject(CHALLENGE_GAMER_OBJ);
		challengeGamerEntry.put(CHALLENGE_GAMER_ID, gamerId);
		challengeGamerEntry.put(CHALLENGE_GAMER_NAME, gamerName);
		challengeGamerEntry.saveInBackground();
		installation.saveInBackground();
	}

	public static ChallengeStatus acceptChallenge(final String message, final Challenge challenge) {
		String challenge_id = challenge.getChallenger() + "_" + System.currentTimeMillis();
		ParseObject challengeEntry = new ParseObject(Challenge.CHALLENGE_OBJ);
		challengeEntry.put(Challenge.CHALLENGER_ID, challenge.getChallenger());
		challengeEntry.put(Challenge.CHALLENGER_OPPONENT_ID, challenge.getChallengerOpponent());
		challengeEntry.put(Challenge.CHALLENGER_NAME, challenge.getChallengerName());
		challengeEntry.put(Challenge.CHALLENGER_OPPONENT_NAME, challenge.getChallengerOpponentName());
		challengeEntry.put(Challenge.CHALLENGER_STATUS, ChallengerStatus.CHALLENGE_ACCEPTED.toString());
		challengeEntry.put(Challenge.CHALLENGER_OPPONENT_STATUS, ChallengerStatus.CHALLENGE_ACCEPTED.toString());
		challengeEntry.put(Challenge.CHALLENGE_ID, challenge_id);
		challengeEntry.put(Challenge.MATCH_TYPE, challenge.getMatchType());
		challengeEntry.put(Challenge.CHALLENGE_STATUS, ChallengeStatus.WAIT.toString());
		challengeEntry.put(Challenge.CHALLENGER_SCORE, 0);
		challengeEntry.put(Challenge.CHALLENGER_OPPONENT_SCORE, 0);
		challenge.setChallengerStatus(ChallengerStatus.CHALLENGE_ACCEPTED.toString());
		challenge.setChallengerOpponentStatus(ChallengerStatus.CHALLENGE_ACCEPTED.toString());
		challenge.setChallengeID(challenge_id);
		challenge.setChallengeStatus(ChallengeStatus.WAIT.toString());
		challenge.setChallengerScore(0);
		challenge.setChallengerOpponentScore(0);
		challengeEntry.saveInBackground(new SaveCallback() {

			@Override
			public void done(ParseException e) {
				ParseQuery findChallengeQuery = ParseInstallation.getQuery();
				findChallengeQuery.whereEqualTo(Challenge.CHALLENGER_ID, challenge.getChallenger());
				ParsePush push = new ParsePush();
				push.setQuery(findChallengeQuery);
				push.setData(createChallengeDataPushObj(challenge, message, ACTION_ACCEPT_CHALLENGE));
				push.sendInBackground(new SendCallback() {

					@Override
					public void done(ParseException e) {
						DLog.d(TAG, "Accept push sent!");
					}
				});

			}
		});

		return ChallengeStatus.WAIT;
	}

	public static Challenge findCasualOpenChallenge(String matchType) {
		try {
			ParseQuery findChallengeQuery = new ParseQuery(CHALLENGE_GAMER_OBJ);
			findChallengeQuery.setLimit(1);
			// TODO: set query according the object time creation
			List<ParseObject> gamer = findChallengeQuery.find();
			if (gamer.size() > 0) {
				Challenge challenge = new Challenge();
				challenge.setChallenger(ChallengeUtils.gamerId);
				challenge.setChallengerName(ChallengeUtils.gamerName);
				challenge.setChallengerOpponent((gamer.get(0)).getString(CHALLENGE_GAMER_ID));
				challenge.setChallengerOpponentName((gamer.get(0)).getString(CHALLENGE_GAMER_NAME));
				challenge.setChallengerStatus(ChallengerStatus.CHALLENGE_PROPOSED.toString());
				challenge.setChallengerOpponentStatus(ChallengerStatus.NO_CHALLENGER.toString());
				challenge.setMatchType(matchType);
				challenge.setChallengeStatus(ChallengeStatus.INIT.toString());
				challenge.setChallengerScore(0);
				challenge.setChallengerOpponentScore(0);
				DLog.d(TAG, "Found challenger: " + (gamer.get(0)).getString(CHALLENGE_GAMER_ID) + " named: " + (gamer.get(0)).getString(CHALLENGE_GAMER_NAME));
				return challenge;
			} else {
				return null;
			}

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static void proposeChallenge(Challenge challenge, String message) {
		DLog.i(TAG, "" + challenge.toString());
		ParseQuery findChallengeQuery = ParseInstallation.getQuery();
		findChallengeQuery.whereEqualTo(CHALLENGE_GAMER_ID, challenge.getChallengerOpponent());
		ParsePush push = new ParsePush();
		push.setQuery(findChallengeQuery);
		push.setData(createChallengeDataPushObj(challenge, message, ACTION_PROPOSE_CHALLENGE));
		push.sendInBackground(new SendCallback() {

			@Override
			public void done(ParseException e) {
				DLog.d(TAG, "Propose push sent!");
			}
		});

	}

	public static void startChallengeAsChallenger(Challenge challenge, String message) {
		DLog.d(TAG, "Start Challenge As Challenger. Challenge is: " + challenge.getChallengeID() + " Challenger is : " + challenge.getChallenger());
		ParseQuery query = new ParseQuery(Challenge.CHALLENGE_OBJ);
		query.whereEqualTo(Challenge.CHALLENGE_ID, challenge.getChallengeID());
		List<ParseObject> remoteChallenges;
		try {
			remoteChallenges = query.find();

			if (remoteChallenges != null && remoteChallenges.size() > 0) {
				ParseObject remoteChallengeSync = remoteChallenges.get(0);

				remoteChallengeSync.put(Challenge.CHALLENGE_STATUS, ChallengeStatus.RUNNING.toString());
				remoteChallengeSync.put(Challenge.CHALLENGER_STATUS, ChallengerStatus.CHALLENGE_STARTED.toString());

				challenge.setChallengeStatus(ChallengeStatus.RUNNING.toString());
				challenge.setChallengerStatus(ChallengerStatus.CHALLENGE_STARTED.toString());

				remoteChallengeSync.saveInBackground();

				ParseQuery findChallengeQuery = ParseInstallation.getQuery();
				findChallengeQuery.whereEqualTo(Challenge.CHALLENGER_ID, challenge.getChallenger());
				ParsePush push = new ParsePush();
				push.setQuery(findChallengeQuery);
				push.setData(createChallengeDataPushObj(challenge, message, ACTION_START_CHALLENGE));
				push.sendInBackground(new SendCallback() {

					@Override
					public void done(ParseException e) {
						DLog.d(TAG, "Started push sent!");
					}
				});

			}
		} catch (ParseException e1) {
			// e1.printStackTrace();
			DLog.e(TAG, "Error sending push!");
		}
	}

	public static void startChallengeAsChallengerOpponent(Challenge challenge, String message) {
		DLog.d(TAG, "Start Challenge As Challenger Opponent. Challenge is: " + challenge.getChallengeID() + " Challenger Opponent is : " + challenge.getChallengerOpponent());
		ParseQuery query = new ParseQuery(Challenge.CHALLENGE_OBJ);
		query.whereEqualTo(Challenge.CHALLENGE_ID, challenge.getChallengeID());
		List<ParseObject> remoteChallenges;
		try {
			remoteChallenges = query.find();

			if (remoteChallenges != null && remoteChallenges.size() > 0) {
				ParseObject remoteChallengeSync = remoteChallenges.get(0);

				remoteChallengeSync.put(Challenge.CHALLENGE_STATUS, ChallengeStatus.RUNNING.toString());
				remoteChallengeSync.put(Challenge.CHALLENGER_OPPONENT_STATUS, ChallengerStatus.CHALLENGE_STARTED.toString());

				challenge.setChallengeStatus(ChallengeStatus.RUNNING.toString());
				challenge.setChallengerOpponentStatus(ChallengerStatus.CHALLENGE_STARTED.toString());

				remoteChallengeSync.saveInBackground();

				ParseQuery findChallengeQuery = ParseInstallation.getQuery();
				findChallengeQuery.whereEqualTo(Challenge.CHALLENGER_ID, challenge.getChallenger());
				ParsePush push = new ParsePush();
				push.setQuery(findChallengeQuery);
				push.setData(createChallengeDataPushObj(challenge,message, ACTION_START_CHALLENGE));
				push.sendInBackground(new SendCallback() {

					@Override
					public void done(ParseException e) {
						DLog.d(TAG, "Started push sent!");
					}
				});

			}
		} catch (ParseException e1) {
			// e1.printStackTrace();
			DLog.e(TAG, "Error sending push!");
		}
	}

	private static JSONObject createChallengeDataPushObj(Challenge challenge, String message, String action) {
		try {
			JSONObject data = new JSONObject("{\"action\": \"" + action + "\"," + "\"" + Challenge.CHALLENGE_ID + "\": \"" + challenge.getChallengeID() + "\"," + "\"" + NOTIFICATION_MESSAGE + "\": \"" + message + "\"," + "\"" + Challenge.CHALLENGER_ID + "\": \"" + challenge.getChallenger() + "\"," + "\""
					+ Challenge.CHALLENGER_OPPONENT_ID + "\": \"" + challenge.getChallengerOpponent() + "\"," + "\"" + Challenge.CHALLENGER_NAME + "\": \"" + challenge.getChallengerName() + "\"," + "\"" + Challenge.CHALLENGER_OPPONENT_NAME + "\": \"" + challenge.getChallengerOpponentName() + "\"," + "\"" + Challenge.CHALLENGER_STATUS
					+ "\": \"" + challenge.getChallengerStatus() + "\"," + "\"" + Challenge.CHALLENGER_OPPONENT_STATUS + "\": \"" + challenge.getChallengerOpponentStatus() + "\"," + "\"" + Challenge.MATCH_TYPE + "\": \"" + challenge.getMatchType() + "\"," + "\"" + Challenge.CHALLENGE_STATUS + "\": \""
					+ challenge.getChallengeStatus() + "\"," + "\"" + Challenge.CHALLENGER_SCORE + "\": \"" + challenge.getChallengerScore() + "\"," + "\"" + Challenge.CHALLENGER_OPPONENT_SCORE + "\": \"" + challenge.getChallengerOpponentScore() + "\"}");
			return data;
		} catch (JSONException e) {
			// e.printStackTrace();
			DLog.e(TAG, "Error craeting push data!");
		}
		return null;

	}

	public static void finishChallengeAsChallenger(Challenge challenge, int score, String message) {
		DLog.d(TAG, "Finished Challenge As Challenger. Challenge is: " + challenge.getChallengeID() + " Challenger is : " + challenge.getChallenger());
		ParseQuery query = new ParseQuery(Challenge.CHALLENGE_OBJ);
		query.whereEqualTo(CHALLENGE_GAMER_ID, challenge.getChallengeID());
		List<ParseObject> remoteChallenges;
		try {
			remoteChallenges = query.find();

			if (remoteChallenges != null && remoteChallenges.size() > 0) {
				ParseObject remoteChallengeSync = remoteChallenges.get(0);
				if (remoteChallengeSync.getString(Challenge.CHALLENGER_OPPONENT_STATUS).equals(ChallengerStatus.CHALLENGE_STARTED)) {
					remoteChallengeSync.put(Challenge.CHALLENGE_STATUS, ChallengeStatus.RUNNING.toString());
					remoteChallengeSync.put(Challenge.CHALLENGER_STATUS, ChallengerStatus.CHALLENGE_FINISHED.toString());
					challenge.setChallengeStatus(ChallengeStatus.RUNNING.toString());
					challenge.setChallengerStatus(ChallengerStatus.CHALLENGE_FINISHED.toString());
				} else {
					remoteChallengeSync.put(Challenge.CHALLENGE_STATUS, ChallengeStatus.FINISHED.toString());
					remoteChallengeSync.put(Challenge.CHALLENGER_STATUS, ChallengerStatus.CHALLENGE_FINISHED.toString());
					challenge.setChallengeStatus(ChallengeStatus.FINISHED.toString());
					challenge.setChallengerStatus(ChallengerStatus.CHALLENGE_FINISHED.toString());
				}

				remoteChallengeSync.saveInBackground();

				ParseQuery findChallengeQuery = ParseInstallation.getQuery();
				findChallengeQuery.whereEqualTo(Challenge.CHALLENGER_ID, challenge.getChallenger());
				ParsePush push = new ParsePush();
				push.setQuery(findChallengeQuery);
				push.setData(createChallengeDataPushObj(challenge,message, ACTION_FINISHED_CHALLENGE));
				push.sendInBackground(new SendCallback() {

					@Override
					public void done(ParseException e) {
						DLog.d(TAG, "Finish push sent!");
					}
				});

			}
		} catch (ParseException e1) {
			// e1.printStackTrace();
			DLog.e(TAG, "Error sending push!");
		}
	}

	public static void finishChallengeAsChallengerOpponent(Challenge challenge, int score, String message) {
		DLog.d(TAG, "Finished Challenge As Challenger Opponent. Challenge is: " + challenge.getChallengeID() + " Challenger Opponent is : " + challenge.getChallengerOpponent());
		ParseQuery query = new ParseQuery(Challenge.CHALLENGE_OBJ);
		query.whereEqualTo(Challenge.CHALLENGE_ID, challenge.getChallengeID());
		List<ParseObject> remoteChallenges;
		try {
			remoteChallenges = query.find();

			if (remoteChallenges != null && remoteChallenges.size() > 0) {
				ParseObject remoteChallengeSync = remoteChallenges.get(0);
				if (remoteChallengeSync.getString(Challenge.CHALLENGER_STATUS).equals(ChallengerStatus.CHALLENGE_STARTED)) {
					remoteChallengeSync.put(Challenge.CHALLENGE_STATUS, ChallengeStatus.RUNNING.toString());
					remoteChallengeSync.put(Challenge.CHALLENGER_OPPONENT_STATUS, ChallengerStatus.CHALLENGE_FINISHED.toString());
					challenge.setChallengeStatus(ChallengeStatus.RUNNING.toString());
					challenge.setChallengerOpponentStatus(ChallengerStatus.CHALLENGE_FINISHED.toString());
				} else {
					remoteChallengeSync.put(Challenge.CHALLENGE_STATUS, ChallengeStatus.FINISHED.toString());
					remoteChallengeSync.put(Challenge.CHALLENGER_OPPONENT_STATUS, ChallengerStatus.CHALLENGE_FINISHED.toString());
					challenge.setChallengeStatus(ChallengeStatus.FINISHED.toString());
					challenge.setChallengerOpponentStatus(ChallengerStatus.CHALLENGE_FINISHED.toString());
				}

				remoteChallengeSync.saveInBackground();

				ParseQuery findChallengeQuery = ParseInstallation.getQuery();
				findChallengeQuery.whereEqualTo(Challenge.CHALLENGER_ID, challenge.getChallenger());
				ParsePush push = new ParsePush();
				push.setQuery(findChallengeQuery);
				push.setData(createChallengeDataPushObj(challenge,message, ACTION_FINISHED_CHALLENGE));
				push.sendInBackground(new SendCallback() {

					@Override
					public void done(ParseException e) {
						DLog.d(TAG, "Finish push sent!");
					}
				});

			}
		} catch (ParseException e1) {
			// e1.printStackTrace();
			DLog.e(TAG, "Error sending push!");
		}
	}
}
